import fs from 'fs'
import { createHash } from 'crypto'
import type { HashOptions } from 'crypto'

export function md5(buf: Buffer) {
  return createHash('md5').update(buf).digest('hex')
}

/**
 * 获取文件hash
 */
export function getFileHash(filePath: string, options?: FileHashOptions) {
  return new Promise<string>((resolve, reject) => {
    if (!fs.existsSync(filePath)) {
      reject(new Error('File not found'))
      return
    }
    const { progress = () => {}, algorithm = 'md5', hashOptions, readStreamOptions } = options || {}

    const hash = createHash(algorithm, hashOptions)
    const stream = fs.createReadStream(filePath, readStreamOptions)
    let current = 0

    stream.on('data', (data) => {
      current += data.length
      hash.update(data)
      progress(current)
    })

    stream.on('end', () => {
      const fileHash = hash.digest('hex')
      resolve(fileHash)
    })

    stream.on('error', (error) => {
      reject(error)
    })
  })
}

type FileHashOptions = {
  progress?: (current: number) => void
  algorithm?: HashAlgorithm
  hashOptions?: HashOptions
  readStreamOptions?: object
}

export type HashAlgorithm =
  | 'md5'
  | 'sha1'
  | 'sha224'
  | 'sha256'
  | 'sha384'
  | 'sha512'
  | 'sha3-224'
  | 'sha3-256'
  | 'sha3-384'
  | 'sha3-512'
  | 'shake128'
  | 'shake256'
